package com.erp.auto.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.erp.auto.mapper.ErpAutoPulishProductProjectTaskMapper;
import com.erp.auto.service.IErpAutoPulishProductProjectTaskService;
import com.ruoyi.auto.api.domain.ErpAutoSellerStoreConfig;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.gather.api.domain.dto.AeAutoProductDto;
import com.ruoyi.auto.api.domain.ErpAutoPulishProductProjectTask;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.gather.api.domain.dto.TaskStatusDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import static jodd.util.ThreadUtil.sleep;

/**
 * 自动化上架计划
 *
 * @author erp
 * @date 2023-12-25
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/auto/publish/task")
public class ErpAutoPulishProductProjectTaskController {

    @Autowired
    IErpAutoPulishProductProjectTaskService erpAutoPulishProductProjectTaskService;
    @Resource
    private RabbitTemplate rabbitTemplate = SpringUtils.getBean(RabbitTemplate.class);

    private final ErpAutoPulishProductProjectTaskMapper erpAutoPulishProductProjectTaskMapper;

    /**
     * 获取当前时间之前的所有未执行的上架计划
     */
    @GetMapping("/updatePublishTaskStatusByCurrentTime/{id}")
    public R<Object> updatePublishTaskStatusByCurrentTime(@PathVariable("id") String id) {
        return erpAutoPulishProductProjectTaskService.updatePublishTaskStatusByCurrentTime(id);
    }

    /**
     * 测试发布
     */
    @GetMapping("/runPublishTestProductToAe/{collectProductId}/{type}")
    public R<Object> runPublishTestProductToAe(@PathVariable("collectProductId") Long collectProductId,@PathVariable("type") Integer type) {
        return erpAutoPulishProductProjectTaskService.runPublishTestProductToAe(collectProductId,type);
    }

    /**
     * 执行计划2.0 执行自动化上架任务
     */
    @GetMapping("/runPublishProductTask/{id}")
    public R<String> runPublishProductTask(@PathVariable("id") String id) {
        ArrayList<Future<AeAutoProductDto>> resultList = new ArrayList<>();
        Map<Long, Future<AeAutoProductDto>> resultMap = new ConcurrentHashMap<>();
        Future<AeAutoProductDto> future = null;
        if (id.equals("null")) {
            R<Object> taskListR = erpAutoPulishProductProjectTaskService.updatePublishTaskStatusByCurrentTime(null);
            if (taskListR.getCode() != 200) {
                return R.ok("暂无可执行任务");
            }

            String taskListRJSONString = JSONObject.toJSONString(taskListR.getData());
            List<ErpAutoPulishProductProjectTask> publishTaskList =
                    JSONArray.parseArray(taskListRJSONString, ErpAutoPulishProductProjectTask.class);
            //生成11位的批次id
            String jobBatchId = RandomUtil.randomNumbers(11);
            // 2、遍历执行发布任务
            if (publishTaskList != null && publishTaskList.size() > 0) {
//                int i = 1;
                for (ErpAutoPulishProductProjectTask task : publishTaskList) {
                    //将批次id放入
                    task.setJobBatchId(Long.valueOf(jobBatchId));
                    future = erpAutoPulishProductProjectTaskService.runPublishProductToAe(task);
                    resultMap.put(task.getId(), future);
//                    i++;
                }
            } else {
                return R.ok("暂无可执行任务");
            }
        } else {
            ErpAutoPulishProductProjectTask task = erpAutoPulishProductProjectTaskMapper.selectById(id);
            future = erpAutoPulishProductProjectTaskService.runPublishProductToAe(task);
            resultMap.put(task.getId(), future);
        }
        runPublishProductToAe(resultMap);
        return R.ok("执行完成");
    }

    /**
     * 执行自动化上架异常任务
     */
    @GetMapping("/runNeedErrorPublishProductTask")
    public R<String> runNeedErrorPublishProductTask() {
        ArrayList<Future<AeAutoProductDto>> resultList = new ArrayList<>();
        Map<Long, Future<AeAutoProductDto>> resultMap = new ConcurrentHashMap<>();
        Future<AeAutoProductDto> future = null;

        List<ErpAutoPulishProductProjectTask> publishTaskList = erpAutoPulishProductProjectTaskMapper.selectList(
                new LambdaQueryWrapper<ErpAutoPulishProductProjectTask>()
                        .eq(ErpAutoPulishProductProjectTask::getStatus, 500)
        );
        //生成11位的批次id
        String jobBatchId = RandomUtil.randomNumbers(11);
        // 2、遍历执行发布任务
        if (publishTaskList != null && publishTaskList.size() > 0) {
//                int i = 1;
            for (ErpAutoPulishProductProjectTask task : publishTaskList) {
                //将批次id放入
                task.setJobBatchId(Long.valueOf(jobBatchId));
                future = erpAutoPulishProductProjectTaskService.runPublishProductToAe(task);
                resultMap.put(task.getId(), future);
//                    i++;
            }
        } else {
            return R.ok("暂无可执行任务");
        }
        runPublishProductToAe(resultMap);
        return R.ok("执行完成");
    }



    /**
     * 重新设置联盟折扣 重设联盟折扣
     * 情况1 将 联盟折扣设置异常 的处理
     *
     * @return
     */
    @GetMapping("setCommissionAgainOne")
    public R<Object> setCommissionAgainOne() {
        return erpAutoPulishProductProjectTaskService.setCommissionAgainOne();
    }

    /**
     * 重新设置联盟折扣 重设联盟折扣
     * 情况2 将用户cookie过期的处理
     *
     * @return
     */
    @GetMapping("setCommissionAgainTwo")
    public R<Object> setCommissionAgainTwo() {
        return erpAutoPulishProductProjectTaskService.setCommissionAgainTwo();
    }

    /**
     * 补发消息队列
     *
     * @param id
     * @return
     */
    @GetMapping("/reissueMessageQueue/{id}")
    public R<Object> reissueMessageQueue(@PathVariable("id") String id) {
        if (id.equals("null")) {
            List<ErpAutoPulishProductProjectTask> taskList = erpAutoPulishProductProjectTaskMapper.selectList(
                    new LambdaQueryWrapper<ErpAutoPulishProductProjectTask>()
                            .eq(ErpAutoPulishProductProjectTask::getStatus, 911)
                            .last("limit 500")
            );

            // 2、遍历执行发布任务
            if (taskList != null && taskList.size() > 0) {
                for (ErpAutoPulishProductProjectTask task : taskList) {
                    AeAutoProductDto dto = erpAutoPulishProductProjectTaskService.reissueMessageQueue(task);
                    if (ObjectUtils.isNull(dto)) {
                        continue;
                    }
                    dto.setAeProductId(task.getAeProductId());
                    distributeTaskCreateData(JSONObject.toJSONString(dto), task.getId());
                }
            } else {
                return R.ok("暂无可执行任务");
            }
        } else {
            ErpAutoPulishProductProjectTask task = erpAutoPulishProductProjectTaskMapper.selectById(id);
            AeAutoProductDto dto = erpAutoPulishProductProjectTaskService.reissueMessageQueue(task);
            dto.setAeProductId(task.getAeProductId());
            distributeTaskCreateData(JSONObject.toJSONString(dto), task.getId());
        }
        return R.ok("执行完成");
    }

    public void runPublishProductToAe(Map<Long, Future<AeAutoProductDto>> resultMap) {
        try {
            while (resultMap.size() > 0) {
                System.out.println("------1------resultMapSize=" + resultMap.size() + "------------");
                // 设立一个休眠机制，如果遍历MAP，异步没有返回值，则等待
                boolean isWait = true;
                // 标识符，防止死循环
                int i = 0;
                System.out.println("-----2-------i=" + i + "------------");
                for (Long key : resultMap.keySet()) {
                    System.out.println("-----3-------key=" + key + "------------");
                    if (resultMap.get(key).isDone()) {
                        System.out.println("-----4-------key=" + key + ", done------------");
                        AeAutoProductDto dto = resultMap.get(key).get();
                        System.out.println(dto.toString());
                        if (dto.getCode() == 200) {
                            //进行队列分发
                            distributeTaskCreateData(JSONObject.toJSONString(dto), key);
                        }
                        // 移除
                        resultMap.remove(key);
                        // 异步已经有返回值，则无需等待
                        isWait = false;
                    } else {
                        continue;
                    }
                }
                // 如果当前循环没有一个异步返回，则等待5S
                System.out.println("-----5-------loop end------------" + isWait);
                if (isWait) {
                    i++;
                    // 防止死循环，即如果等待超过30分钟，则退出循环，并打印错误日志 12 * 30
                    if (i > 360) {
                        System.out.println("-----7-------while loop end------------" + i);
                        break;
                    }
                    System.out.println("-----6-------sleep------------");
                    sleep(5000);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    private void distributeTaskCreateData(String resultStr, Long id) {
        // 转换实体类，并转成JSON字符串
        // 4、将字符串进行分发
        // 4.1 分发至gather业务模块，进行公共库至个人库操作
        log.info("开始分发至gather业务模块，进行公共库至个人库操作:" + id);
        rabbitTemplate.convertAndSend("auto-event-exchange", "auto.seller.product.insert", resultStr);
        log.info("进行公共库至个人库操作结束:" + id);

    }

    /**
     * 更新任务状态及备注
     *
     * @param dto
     * @return
     */
    @PostMapping("/updateTaskStatus")
    public R<Object> updateTaskStatus(@RequestBody TaskStatusDto dto) {
        String id = dto.getId();
        Integer status = dto.getStatus();
        String msg = dto.getMsg();
        return erpAutoPulishProductProjectTaskService.updateTaskStatus(id, status, msg);
    }

    @GetMapping("/deleteTortListByCollectProductId/{collectProductId}")
    public R<Object> deleteTortListByCollectProductId(@PathVariable("collectProductId") String collectProductId) {
        return erpAutoPulishProductProjectTaskService.deleteTortListByCollectProductId(collectProductId);
    }


    /**
     * 重复上品问题解决
     */
    @GetMapping("/repeatPublishErrorByStoreId")
    public R<Object> repeatPublishErrorByStoreId(Long storeId) {
        return erpAutoPulishProductProjectTaskService.queryRepeatPublishErrorByStoreId(storeId);
    }

    @GetMapping("/repeatPublishErrorAllStore")
    public R<Object> repeatPublishErrorAllStore(Integer type) {
        switch (type) {
            case 1:
                //确认是否有重复上架的品 处理是500的品
                return erpAutoPulishProductProjectTaskService.queryRepeatPublishErrorAllStore();
            case 2:
                //将502状态的任务重新下架
                return erpAutoPulishProductProjectTaskService.unshelfRepeatErrorTaskAllStore();
            case 3:
                //将501状态的任务删除
                return erpAutoPulishProductProjectTaskService.deleteRepeatErrorTaskAllStore();
            default:
                return R.fail("异常");
        }

    }

    /**
     * 检测活动设置异常，调用爬虫接口重新设置活动 并处理
     */
    @GetMapping("/checkActivityErrorHandle")
    public R<Object> checkActivityErrorHandle() {
        return erpAutoPulishProductProjectTaskService.checkActivityErrorHandle();
    }

}
